package net.jxtz.jxtzos.spider.process;


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import net.jxtz.jxtzos.entity.spider.SpiderJingdong;
import net.jxtz.jxtzos.entity.spider.SpiderLogServe;
import net.jxtz.jxtzos.service.spider.ISpiderJingdongService;
import net.jxtz.jxtzos.spider.BaseSpiderProcessor;
import net.jxtz.jxtzos.spider.SpiderDefinition;
import net.jxtz.jxtzos.spider.SpiderFactory;
import net.jxtz.jxtzos.util.StampToDateAndDateToStamp;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 京东拍卖
 */

@Slf4j
@Component
public class JingDongProcessor implements BaseSpiderProcessor {

    public static final String SPIDER_NAME = "jingdong";

    private static final int MAX_PAGE = 50;

    private Long spiderLogId = null;

    public JingDongProcessor() {
        SpiderFactory instance = SpiderFactory.getInstance();
        instance.putSpiderProcess(SPIDER_NAME, this);
        SpiderDefinition jingdong = new SpiderDefinition("京东司法拍卖", SPIDER_NAME);
        jingdong.setImgUrl("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.zcool.cn%2Fcommunity%2F019a685be41e2fa80121ab5d34ce6f.jpg%403000w_1l_0o_100sh.jpg&refer=http%3A%2F%2Fimg.zcool.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1634455898&t=7f388afb48d5852b20eb1eb186b0d717");
        instance.putSpiderDefinition(SPIDER_NAME, jingdong);
    }

    @Autowired
    private ISpiderJingdongService jingdongService;

    private Integer updateCount;

    private Integer lastTime;

    public Integer getLastTime() {
        return lastTime;
    }

    @Autowired
    private ISpiderJingdongService service;

    public Integer getUpdateCount() {
        return updateCount;
    }

    // 当前时间戳，毫秒级
    private final String nowStamp = StampToDateAndDateToStamp.dateToStamp("", "yyyy-MM-dd HH:mm:ss");


    // 根据首页返回的请求拿到每个商品的id，返回映射好的实体类数组
    private boolean process(Integer minPage, String childrenCateId) {
        List<SpiderJingdong> spiderJingdongs = new ArrayList<>();

        // 翻页url
        String pageUrlPrefix = "https://api.m.jd.com/api?appid=paimai-search-soa&functionId=paimai_unifiedSearch&body=%7B%22apiType%22:2,%22page%22:%22";
        String pageUrlSuffix = "%22,%22pageSize%22:40,%22reqSource%22:0,%22childrenCateId%22:%22" + childrenCateId + "%22,%22provinceId%22:21,%22paimaiStatus%22:%222%22%7D&loginType=3&jsonp=jQuery4320528&_=";
        String pageUrl = pageUrlPrefix + minPage + pageUrlSuffix + nowStamp;

        String s = httpGetFormate(pageUrl);

        assert s != null;
        log.info(childrenCateId + "：请求成功");
        String s1 = resetJsonFormat(s);
        // 字符串转json
        JSONObject jsonObject = JSONObject.parseObject(s1);
        // 去除key为datas的value，是个arr数组
        JSONArray datas = jsonObject.getJSONArray("datas");
        if (datas.size() == 0) return false;
        for (int i = 0; i < datas.size(); i++) {
            SpiderJingdong sj = new SpiderJingdong();

            SpiderJingdong spiderJingdong = datas.getObject(i, SpiderJingdong.class);
            // 商品id
            Integer id = spiderJingdong.getId();
            // 成交价
            BigDecimal currentPrice = spiderJingdong.getCurrentPrice();
            String title = spiderJingdong.getTitle();
            Integer paimaiTimes = spiderJingdong.getPaimaiTimes();
            Long endTime = spiderJingdong.getEndTime() / 1000;

            String detailsUrlPrefix = "https://api.m.jd.com/api?appid=paimai&functionId=getProductBasicInfo&body=%7B%22paimaiId%22:";
            String detailsUrlSuffix = "%7D&loginType=3&jsonp=jsonp_" + System.currentTimeMillis() + "_95050";

            String paimaiDetailsDescribePrefix = "https://api.m.jd.com/api?appid=paimai&functionId=queryProductDescription&body=%7B%22paimaiId%22:";
            String paimaiDetailsDescribeSuffix = ",%22source%22:0%7D&loginType=3&jsonp=jsonp_" + System.currentTimeMillis() + "_38626";

            String chengjiaoDesPrefix = "https://api.m.jd.com/api?appid=paimai&functionId=getPaimaiRealTimeData&body=%7B%22end%22:9,%22paimaiId%22:";
            String chengjiaoDesSuffix = ",%22source%22:0,%22start%22:0%7D&loginType=3&jsonp=jsonp_" + System.currentTimeMillis() + "_14031";

            String detailsUrl = detailsUrlPrefix + id + detailsUrlSuffix;
            String sh = httpGetFormate(detailsUrl);
            assert sh != null;
            String jsonFormat = resetJsonFormat(sh);
            JSONObject jsonObject1 = JSONObject.parseObject(jsonFormat);
            SpiderJingdong jingdong = jsonObject1.getObject("data", SpiderJingdong.class);

            String chengjiaoDes = chengjiaoDesPrefix + id + chengjiaoDesSuffix;

            String s4 = httpGetFormate(chengjiaoDes);
            assert s4 != null;
            String s5 = resetJsonFormat(s4);
            JSONObject jsonObject4 = JSONObject.parseObject(s5);

            // 获取成交确认书
            SpiderJingdong data2 = jsonObject4.getObject("data", SpiderJingdong.class);
            sj.setConfirmationUrl(data2.getConfirmationUrl());

            // 拿到评估价
            BigDecimal assessmentPrice = jingdong.getAssessmentPrice();

            // 读取data子对象productAddressResult，解析出地址，省，市，区
            String data1 = jsonObject1.getString("data");
            JSONObject jsonObject2 = JSONObject.parseObject(data1);
            String productAddressResult = jsonObject2.getString("productAddressResult");
            JSONObject jsonObject3 = JSONObject.parseObject(productAddressResult);
            String address = jsonObject3.getString("address");
            String city = jsonObject3.getString("city");
            String county = jsonObject3.getString("county");
            String province = jsonObject3.getString("province");

            Integer albumId = jingdong.getAlbumId();
            BigDecimal startPrice = jingdong.getStartPrice();
            BigDecimal priceLowerOffset = jingdong.getPriceLowerOffset();

            sj.setId(id);
            sj.setAssessmentPrice(assessmentPrice);
            sj.setTitle(title);
            sj.setPaimaiTimes(paimaiTimes);
            sj.setEndTime(endTime);
            sj.setCurrentPrice(currentPrice);
            sj.setAlbumId(albumId);
            sj.setStartPrice(startPrice);
            sj.setPriceLowerOffset(priceLowerOffset);
            sj.setAddress(address);
            sj.setCity(city);
            sj.setCounty(county);
            sj.setProvince(province);
            sj.setUrl("https://paimai.jd.com/" + id);
            switch (childrenCateId) {
                case "12728":
                    sj.setPaimaiChildren("住宅用房");
                    break;
                case "13809":
                    sj.setPaimaiChildren("商业用房");
                    break;
                case "13817":
                    sj.setPaimaiChildren("工业用房");
                    break;
                case "13810":
                    sj.setPaimaiChildren("其他用房");
                    break;
            }

            // 解析拍卖公告html
            String paimaiDetailsDescribeUrl = paimaiDetailsDescribePrefix + id + paimaiDetailsDescribeSuffix;
            String ss = httpGetFormate(paimaiDetailsDescribeUrl);
            assert ss != null;
            String paimaiDetailsDescribe = resetJsonFormat(ss);
            JSONObject parseObject = JSONObject.parseObject(paimaiDetailsDescribe);
            String data = parseObject.getString("data");
            Document document = null;
            try {
                 document = Jsoup.parse(data);
            }catch (Exception e){
                e.printStackTrace();
            }
            assert document != null;
            List<String> td = document.getElementsByTag("td").eachText();
            if (td != null && td.size() != 0) {
                for (String s2 : td) {
                    switch (s2) {
                        case "房屋用途":
                            sj.setHousingUse(td.get(td.indexOf(s2) + 1));
                            break;
                        case "建筑面积":
                        case "建筑总面积":
                            String s3 = td.get(td.indexOf(s2) + 1);
                            sj.setHousingArea(s3);
                            break;
                        case "房屋结构":
                            sj.setHousingBuildStructure(td.get(td.indexOf(s2) + 1));
                            break;
                        case "装修情况":
                            sj.setDecoration(td.get(td.indexOf(s2) + 1));
                            break;
                    }
                }
            }

            if (spiderLogId != null) {
                sj.setSpiderLogId(spiderLogId);
            }
            spiderJingdongs.add(sj);
        }


        boolean b = false;
        try {
            for (SpiderJingdong spiderJingdong : spiderJingdongs) {
                b = jingdongService.save(spiderJingdong);
                log.info("存入数据库：" + b);
            }

        }catch (Exception e){
            e.printStackTrace();
        }

        return true;
    }


    // 返回的实体不是规则的json格式，所以写了一个格式化json的方法过滤一下
    private String resetJsonFormat(String json) {
        String substring = json.substring(json.indexOf("(") + 1, json.length());
        return substring.substring(0, substring.lastIndexOf(")"));
    }

    // 封装http请求
    @SneakyThrows
    private String httpGetFormate(String url) {
//        TimeUnit.SECONDS.sleep(3);
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpGet httpGet = new HttpGet(url);
        httpGet.setHeader("authority", "api.m.jd.com");
        httpGet.setHeader("pragma", "no-cache");
        httpGet.setHeader("cache-control", "no-cache");
        httpGet.setHeader("user-agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36");
        httpGet.setHeader("dnt", "1");
        httpGet.setHeader("accept", "*/*");
        httpGet.setHeader("sec-fetch-site", "same-site");
        httpGet.setHeader("sec-fetch-mode", "no-cors");
        httpGet.setHeader("sec-fetch-dest", "script");
        httpGet.setHeader("referer", "https://auction.jd.com/");
        httpGet.setHeader("accept-language", "zh-CN,zh;q=0.9,en;q=0.8,zh-TW;q=0.7");
        httpGet.setHeader("cookie", "__jdc=122270672; __jdv=122270672|direct|-|none|-|1605081009834; __jdu=16050810098342147051102; areaId=19; ipLoc-djd=19-1601-3633-0; 3AB9D23F7A4B3C9B=LMJ4RJVX6FIAFILXIDEKUJ3NUUVDZCBRW55N4NSGZ7HS226URQRAHQRCMKSIPUUWSBQIDFZCRS2OCQUTA53VSYHACQ; RT=\"z=1&dm=jd.com&si=vcvieq4x8k&ss=khd4ca74&sl=0&tt=0&r=0f6fff7b738cae466a84f0b1371835ad&ul=3h0s&hd=3h0y\"; __jda=122270672.16050810098342147051102.1605081010.1605081010.1605084547.2; __jdb=122270672.4.16050810098342147051102|2.1605084547");
        CloseableHttpResponse response = null;
        HttpEntity entity = null;
        String s = null;
        try {
            response = httpClient.execute(httpGet);
            if (response.getStatusLine().getStatusCode() == 200) {
                log.info(url + "：请求成功");
                entity = response.getEntity();
                s = EntityUtils.toString(entity);
            } else {
                log.info(url + "：请求失败");
                return null;
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return s;
    }

    @Override
    public void start(SpiderLogServe spiderLogServe, SpiderDefinition spiderDefinition) {
        spiderLogId = spiderLogServe.getId();
        long startTime = System.currentTimeMillis() / 1000;
        int startCount = service.count();
        log.info("开始爬取");


        String[] strings = new String[]{"12728", "13809", "13817", "13810"};

        for (String string : strings) {
            int minPage = 1;
            while (minPage <= MAX_PAGE) {
                log.info("当前页：" + minPage);
                boolean process = process(minPage++, string);
                if (!process) break;
                try {
                    TimeUnit.SECONDS.sleep(3);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        log.info("爬取完毕");

        long endTime = System.currentTimeMillis() / 1000;
        long time = endTime - startTime;
        int endCount = service.count();
        updateCount = endCount - startCount;
        lastTime = Long.valueOf(endTime).intValue();
        spiderLogServe.setCount(updateCount);
        spiderLogServe.setExecute(true);
        log.info("爬取完毕，用时：" + time + "s，更新数量：" + updateCount);
    }
}
